﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using UsedBookTradeSystem.DBContext;
using UsedBookTradeSystem.Models.Dtos.InputDtos;
using UsedBookTradeSystem.Models.Dtos.OutputDtos;
using UsedBookTradeSystem.Models.Entity;

namespace UsedBookTradeSystem.Controllers.FrontControllers
{
    public class CartController : Controller
    {
        private readonly SystemDbContext _ctx;

        public CartController(SystemDbContext ctx)
        {
            _ctx = ctx;
        }
        [Authorize(Roles = "User")]
        public async Task<IActionResult> Index()
        {
            var cart = await _ctx.Carts.Include(x => x.User).FirstAsync(x => x.User.UserName == User.Identity.Name);
            var cartInfoOutputs = await _ctx.Books
                .Include(x => x.BookInfo)
                .Where(x => x.Cart == cart)
                .GroupBy(x => x.BookInfo, (k, g) => new CartInfoOutput
                {
                    BookInfoId = k.Id,
                    BookName = k.BookName,
                    BookPicture = k.Picture,
                    BookInventory = k.Inventory,
                    Price = k.Price,
                    BookCount = g.Count(),
                    TotolPrice = g.Count() * k.Price
                }).ToListAsync();

            return View(new CartViewOutput { GoWhere = "", CartInfoOutput = cartInfoOutputs });
        }
        [Authorize(Roles = "User")]
        public async Task<IActionResult> AddCart(int bookId, ushort time)
        {
            var bookinfo = await _ctx.BooksInfo.FirstOrDefaultAsync(x => x.Id == bookId);
            var cart = await _ctx.Carts.Include(x => x.User).FirstAsync(x => x.User.UserName == User.Identity.Name);
            if (bookinfo == null)
            {
                TempData["OperateResult"] = "书籍不存在！";
                return RedirectToAction(nameof(Index));
            }
            if (bookinfo.Inventory < time)
            {
                TempData["OperateResult"] = "超出库存！";
                return RedirectToAction(nameof(Index));
            }
            var bookList = await _ctx.Books.Where(x => x.BookInfo == bookinfo && x.Cart == null && x.IsSell==false)
                .Take(time)
                .ToListAsync();
            bookList.ForEach(x => x.UpdatedTime = DateTime.Now);
            cart.Books = bookList;
            bookinfo.Inventory -= time;
            await _ctx.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        [Authorize(Roles = "User")]
        public async Task<IActionResult> UpdateCart(CartViewOutput CartViewOutput)
        {
            var cart = await _ctx.Carts.Include(x => x.User).Include(x => x.Books).ThenInclude(p => p.BookInfo).FirstAsync(x => x.User.UserName == User.Identity.Name);
            var CartBookOutput = CartViewOutput.CartInfoOutput;
            if (CartBookOutput is null) 
            {
                return CartViewOutput.GoWhere switch
                {
                    "Back" => RedirectToAction("Shop", "Home"),
                    "CheckOut" => RedirectToAction("CheckOut"),
                    _ => RedirectToAction("Shop", "Home")
                };
            }
            foreach (var item in CartBookOutput)
            {
                var bookinfo = await _ctx.BooksInfo.FirstAsync(x => x.Id == item.BookInfoId);
                var change = item.BookCount - cart.Books.Count(x => x.BookInfo.Id == item.BookInfoId);
                List<Book> cartBook;
                if (change > 0)
                {
                    cartBook = await _ctx.Books.Where(x => x.BookInfo == bookinfo && x.IsSell == false && x.Cart == null).Take(change).ToListAsync();
                    cartBook.ForEach(x => { x.IsSell = true; x.UpdatedTime = DateTime.Now; });
                    cart.Books.AddRange(cartBook);
                }
                if (change < 0)
                {
                    cartBook = await _ctx.Books.Include(x => x.BookInfo).Where(x => x.Cart == cart && x.BookInfo == bookinfo && x.IsSell == false).Take(Math.Abs(change)).ToListAsync();
                    cart.Books = cart.Books.Where(x => !cartBook.Select(y => y.Id).Contains(x.Id)).ToList();
                    cartBook.ForEach(x => { x.Cart = null; x.IsSell = false; });
                    _ctx.Books.UpdateRange(cartBook);
                }
                bookinfo.Inventory -= change;
                _ctx.BooksInfo.Update(bookinfo);
            }
            await _ctx.SaveChangesAsync();
            return CartViewOutput.GoWhere switch
            {
                "Back" => RedirectToAction("Shop", "Home"),
                "CheckOut" => RedirectToAction("CheckOut"),
                _ => RedirectToAction("Shop", "Home")
            };
        }

        [Authorize(Roles = "User")]
        public async Task<IActionResult> CheckOut()
        {
            var userInfo = await _ctx.Users.FirstAsync(x => x.UserName == User.Identity.Name);
            var cart = await _ctx.Carts.Include(x => x.User).Include(x => x.Books).ThenInclude(p => p.BookInfo).FirstAsync(x => x.User == userInfo);

            if (cart.Books==null||cart.Books.Count==0)
            {
                TempData["OperateResult"] = "购物车为空，请前往商城页面购物";
                return RedirectToAction(nameof(Index));
            }
            var cartInfoOutputs = await _ctx.Books
                .Include(x => x.BookInfo)
                .Where(x => x.Cart == cart)
                .GroupBy(x => x.BookInfo, (k, g) => new CartInfoOutput
                {
                    BookInfoId = k.Id,
                    BookName = k.BookName,
                    BookPicture = k.Picture,
                    BookInventory = k.Inventory,
                    Price = k.Price,
                    BookCount = g.Count(),
                    TotolPrice = g.Count() * k.Price
                }).ToListAsync();
            ViewBag.User = userInfo;
            ViewBag.Cart = cartInfoOutputs;
            return View();
        }

        [Authorize(Roles = "User")]
        public async Task<IActionResult> MakeOrder(OrderInput orderInput) 
        {
            if (string.IsNullOrWhiteSpace(orderInput.Name) || string.IsNullOrWhiteSpace(orderInput.Address)) 
            {
                TempData["OperateResult"] = "用户名或地址不能为空";
                return RedirectToAction(nameof(CheckOut));
            }
            var userInfo = await _ctx.Users.FirstAsync(x => x.UserName == User.Identity.Name);
            var cart = await _ctx.Carts.Include(x => x.User).Include(x => x.Books).ThenInclude(p => p.BookInfo).FirstAsync(x => x.User == userInfo);
            Order order = new Order();
            order.OrderStatus = Models.Enum.OrderEnum.paid;
            order.User = userInfo;
            order.BookList = cart.Books;
            order.Address = orderInput.Address;
            order.UserName = orderInput.Name;
            order.Tel = orderInput.Tel;
            order.BookList.ForEach(x => { x.IsSell = true; x.Order = order; });
            cart.Books.Clear();
            _ctx.Orders.Add(order);
            _ctx.Carts.Update(cart);
            _ctx.SaveChanges();
            return RedirectToAction("Index","Shopper");
        }
    }
}
